package com.study.talk.module.service.impl;


import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.google.gson.*;
import com.study.talk.common.code.MessageCode;
import com.study.talk.common.util.SessionUtil;
import com.study.talk.module.entity.*;
import com.study.talk.module.mapper.GroupInfoMapper;
import com.study.talk.module.mapper.UserMapper;
import com.study.talk.module.netty.message.TalkMessage;
import com.study.talk.module.service.MessageService;
import com.study.talk.module.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.netty.channel.Channel;
import io.swagger.annotations.ApiModelProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;


/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author thor
 * @since 2023-12-18
 */
@Service
@Slf4j
@Transactional
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private static final String REDIS_MESSAGE_CACHE = "redis_message_cache";

    @Resource
    private MessageService messageService;

    @Resource
    private GroupInfoMapper groupInfoMapper;

    @ApiModelProperty("创建Gson实例并注册自定义序列化和反序列化器")
    final Gson gson = new GsonBuilder()
            .registerTypeAdapter(LocalDateTime.class, (JsonSerializer<LocalDateTime>) (time, type, jsonSerializationContext) -> {
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                return new JsonPrimitive(time.format(formatter));
            })  // 注册序列化器
            .registerTypeAdapter(LocalDateTime.class, (JsonDeserializer<LocalDateTime>) (json, typeOfT, context) -> {
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                return LocalDateTime.parse(json.getAsString(), formatter);
            })  // 注册反序列化器
            .create();


    @Override
    public boolean checkChannelAndCacheMessage(Integer userId, Channel channel, TalkMessage msg) {
        Message message = new Message();
        message.setUserId(userId);
        message.setMessage(gson.toJson(msg));
        message.setType((int) msg.getType());
        if (ObjectUtils.isNull(channel) || !channel.isActive() || !channel.isOpen() || !channel.isWritable()) {
            messageService.addMessage(message);
            return true;
        }
        message.setStatus(1);
        messageService.addMessage(message);
        return false;
    }

    @Override
    public void sendCacheMessage(Integer userId, Channel channel) {
        List<Message> messageList = messageService.getMessageList(userId);
        if (messageList == null || messageList.size() == 0) return;
        for (Message message : messageList) {
            Class<? extends TalkMessage> type = MessageCode.getPacketByMessageType(message.getType().byteValue());
            TalkMessage talkMessage = gson.fromJson(message.getMessage(), type);
            channel.writeAndFlush(message);
            log.debug(talkMessage.getDateTime());
        }
        log.info("发送缓存消息");
    }

    @Override
    public void sendMessage(Integer userId, TalkMessage message) {
        Channel channel = SessionUtil.getChannel(userId);
        boolean b = checkChannelAndCacheMessage(userId, channel, message);
        if (!b) {
            channel.writeAndFlush(message);
        }
    }

    @Override
    public void sendAllMessage(Integer userId, Channel channel) {
        List<Message> messageList = messageService.getAllMessage(userId);
        if (messageList == null || messageList.size() == 0) return;
        for (Message message : messageList) {
            Class<? extends TalkMessage> type = MessageCode.getPacketByMessageType(message.getType().byteValue());
            TalkMessage talkMessage = gson.fromJson(message.getMessage(), type);
            channel.writeAndFlush(message);
            log.info(talkMessage.getDateTime());
        }
    }

    @Override
    public List<Message> getAllMessage(Integer userId) {
        return messageService.getAllMessage(userId);
    }

}
